package cc.verywell.pureblock.msg.nfs.linkmap;

import java.util.ArrayList;
import java.util.List;

/**
* 
* Copyright © 2019 TanYaqiu. All rights reserved.
* @author TanYaqiu 
* @address flat 601
* @date 2019年6月19日 下午1:08:12
*/
public class EasyTableGroup implements EasyTables {

	//private EasyTableMem memTable;
	final private EasyTablesUnsort unsort;
	final private EasyTablesSorted[] sorted;
	
	public EasyTableGroup(EasyTablesUnsort unsort, EasyTablesSorted[] sorted) {
		this.unsort = unsort;
		this.sorted = sorted;
	}

	@Override
	public EasyIteratorGroup get(EasyIteratorGroup group, LinkCell startWith) {
//		EasyTableMem memTable;
//		synchronized (this) {
//			memTable = this.memTable;
//		}
//		EasyIterator memIt = memTable==null?null:memTable.get(startWith);
		
		group = unsort.get(group, startWith);
		for (EasyTables s : sorted) {
			group = s.get(group, startWith);
		}
//		
//		if(memIt!=null) {
//			if(group==null)group = new EasyIteratorGroup();
//			group.add(memIt);
//		}
		
//		if(group!=null)group.next();
		
		return group;
	}
	public LinkCell getFirst(int grade,LinkCell startWith) {
		if(grade<1)throw new IllegalArgumentException("grade == "+grade);
		if(grade>sorted.length)return null;
		
		for(int i = grade-1;i<sorted.length;i++) {
			EasyIterator it = sorted[i].get(startWith);
			if(it!=null && it.hasNext())return it.current();
		}
		return null;
	}
	
	public EasyTablesUnsort getUnsort() {
		return unsort;
	}
	public EasyTablesSorted getSorted(int grade) {
		return sorted[grade-1];
	}
	EasyTablesSorted[] getSorteds() {
		return sorted;
	}
	
	
	////copact相关
	
//	public boolean setMemTable(EasyTableMem memTable) {
//		synchronized (this) {
//			if(null!=this.memTable || null!=compact) {
//				return false;
//			}
//			this.memTable = memTable;
//			return true;
//		}
//	}
	
	private EasyCompact compact;
	private boolean compactchecked = false;
	public EasyCompact needCompact(LinkCell[] lastCompacted) {
		synchronized (this) {
			if(compactchecked) {
				return compact;
			}
			compactchecked = true;
			
			///grade
			int grade = -1;
			List<EasyTableHDhead> flist = null;
			if(unsort.files.size()>4) {
				grade = 0;
				flist = unsort.files;
			}else {
				int g = 0;
				long baseSize = 1024L*1024;// 1M
				for (EasyTablesSorted s : sorted) {
					g++;
					baseSize *= 10;
					long size = 0;
					for (EasyTableHDhead f : s.files) {
						size += f.fileSize();
					}
					if(size>baseSize) {
						grade = g;
						flist = s.files;
						break;
					}
				}
			}
			if(grade<0 || grade>=EasyFileController.MAX_GRADE)return null;
			
			///head
			EasyTableHDhead okhead = null;
			head:{
				for (EasyTableHDhead head : flist) {
					if(lastCompacted[grade]==null || head.end.compareTo(lastCompacted[grade])>0) {
						okhead = head;
						break head;
					}
				}
				okhead = flist.get(0);
			}
			
			///heads
			LinkCell start = okhead.start;
			LinkCell end = okhead.end;
			ArrayList<EasyTableHDhead> headsFrom = new ArrayList<>();
			if(grade==0) {
				for (EasyTableHDhead head : flist) {
					if(head==okhead || head.overap(start, end)) {
						headsFrom.add(head);
					}
				}
				if(!headsFrom.isEmpty()) {
					//有序
					//if(headsFrom.get(0).start.compareTo(start)<0)start = headsFrom.get(0).start;
					if(headsFrom.get(0)!=okhead)start = headsFrom.get(0).start;
					for (EasyTableHDhead head : headsFrom) {
						///无序if(head.start.compareTo(start)<0)start = head.start;
						if(head.end.compareTo(end)>0)end = head.end;
					}
				}
			}
			ArrayList<EasyTableHDhead> headsTo = new ArrayList<>();
			EasyTablesSorted flistTo = sorted[grade];
			{
				boolean inbound = false;
				for (EasyTableHDhead head : flistTo.files) {
					//有序
					if(inbound) {
						if(head.start.compareTo(end)>0)break;
						headsTo.add(head);
					}else {
						if(head.end.compareTo(start)>0) {
							if(head.start.compareTo(end)>0)break;
							inbound = true;
							headsTo.add(head);
						}
					}
					///无序if(head.overap(start, end))	headsTo.add(head);
				};
			}
			if(!headsTo.isEmpty()) {
				//有序
				if(headsTo.get(0).start.compareTo(start)<0)start = headsTo.get(0).start;
				if(headsTo.get(headsTo.size()-1).end.compareTo(end)>0)end = headsTo.get(headsTo.size()-1).end;
				///无序for (EasyTableHDhead head : headsTo) {
				///无序	if(head.start.compareTo(start)<0)start = head.start;
				///无序	if(head.end.compareTo(end)>0)end = head.end;
				///无序}
				ArrayList<EasyTableHDhead> headsFrom2 = new ArrayList<>();
				for (EasyTableHDhead head : flist) {
					if(head==okhead || head.overap(start, end)) {
						headsFrom2.add(head);
					}
				}
				if(headsFrom2.size()>headsFrom.size()) {
					LinkCell start2 = start;
					LinkCell end2 = end;
					//有序
					if(headsFrom2.get(0)!=headsFrom.get(0))start2 = headsFrom2.get(0).start;
					for (EasyTableHDhead head : headsFrom2) {
						///无序if(head.start.compareTo(start2)<0)start2 = head.start;
						if(head.end.compareTo(end2)>0)end2 = head.end;
					}
					ArrayList<EasyTableHDhead> headsTo2 = new ArrayList<>();
					{
						boolean inbound = false;
						for (EasyTableHDhead head : flistTo.files) {
							//有序
							if(inbound) {
								if(head.start.compareTo(end2)>0)break;
								headsTo2.add(head);
							}else {
								if(head.end.compareTo(start2)>0) {
									if(head.start.compareTo(end2)>0)break;
									inbound = true;
									headsTo2.add(head);
								}
							}
							///无序if(head.overap(start2, end2))	headsTo2.add(head);
						};
					}
					if(headsTo.size()==headsTo2.size()) {
						headsFrom = headsFrom2;
						start = start2;
						end = end2;
					}
				}
			}
			//headsFrom.add(okhead);
			ArrayList<EasyTableHDhead> headsBound = new ArrayList<>();
			if(grade+1<sorted.length) {
				EasyTablesSorted flistBound = sorted[grade+1];
				for (EasyTableHDhead head : flistBound.files) {
					if(head.overap(start, end)) {
						headsBound.add(head);
					}
				};
			}
			
			return compact = new EasyCompactGrade(grade, headsFrom, headsTo, headsBound, lastCompacted);
		}
	}
	

	
	

}
